﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.OleDb;
using System.Linq;
using Sorteo.BusinessEntities;

namespace Sorteo.DataObjects
{
    public class DOPromocion: DOBase
    {
        #region Declarations

        private const string GetListSP = "proc_PromocionLoadAll";
        private const string GetSorteoListSP = "proc_SorteoLoadAll";
        //private const string GetByIdSP = "proc_PromocionLoadByPrimaryKey";
        private const string DeleteSP = "proc_PromocionDelete";
        private const string UpdateSP = "proc_PromocionUpdate";
        private const string InsertSP = "proc_PromocionInsert";
        private const string InsertSorteoSP = "proc_SorteoInsert";
        private const string InsertCargaExcelSP = "proc_CargaExcelInsert";
        private const string CalculaAccionesSP = "proc_CalculaAcciones";
        private const string CleanupSP = "proc_Cleanup";
        private const string EjecutaSorteoSP = "proc_EjecutaSorteo";
        private const string EjecutaSorteoPorFechasSP = "proc_EjecutaSorteoPorFechas";
        private const string ReporteConcursantesSP = "proc_ReporteConcursantes";

        #endregion

        #region Methods: Public

        public static List<BEPromocion> GetList()
        {
            var result = new List<BEPromocion>();
            var command = Db.GetStoredProcCommand(GetListSP);
            var data = Db.ExecuteDataSet(command);
            var sorteos = GetSorteoList();

            if (data.Tables.Count == 1)
            {
                foreach (DataRow row in data.Tables[0].Rows)
                {
                    var promocion = CreateEntityFromDataRow<BEPromocion>(row);
                    var sorteosEnPromocion = from s in sorteos where s.PromocionId == promocion.Id select s;
                    foreach(var item in sorteosEnPromocion)
                        promocion.Sorteos.Add(item);
                    result.Add(promocion);
                }
            }
            return result;
        }

        public static void Insert(BEPromocion promocion)
        {
            var command = Db.GetStoredProcCommand(InsertSP);
            Db.AddOutParameter(command, "@Id", DbType.Int32, 4);
            Db.AddInParameter(command, "@nombre", DbType.String, promocion.Nombre);
            Db.AddInParameter(command, "@fechaInicio", DbType.DateTime, promocion.FechaInicio);
            Db.AddInParameter(command, "@fechaFinal", DbType.DateTime, promocion.FechaFinal);
            Db.AddInParameter(command, "@fechaCreacion", DbType.DateTime, DateTime.Now);
            Db.AddInParameter(command, "@Monto", DbType.Decimal, promocion.Monto);
            Db.AddInParameter(command, "@CantidadAcciones", DbType.Int32, promocion.CantidadAcciones);
            Db.AddInParameter(command, "@favorecerMultiplesVeces", DbType.Boolean, promocion.FavorecerMultiplesVeces);
            Db.ExecuteNonQuery(command);
            var promocionId = Convert.ToInt32(Db.GetParameterValue(command, "@Id"));
            InsertSorteos(promocion.Sorteos, promocionId);
        }

        public static void Update(BEPromocion promocion)
        {
            var command = Db.GetStoredProcCommand(UpdateSP);
            Db.AddInParameter(command, "@Id", DbType.Int32, promocion.Id);
            Db.AddInParameter(command, "@nombre", DbType.String, promocion.Nombre);
            Db.AddInParameter(command, "@fechaInicio", DbType.DateTime, promocion.FechaInicio);
            Db.AddInParameter(command, "@fechaFinal", DbType.DateTime, promocion.FechaFinal);
            Db.AddInParameter(command, "@fechaCreacion", DbType.DateTime, DateTime.Now);
            Db.AddInParameter(command, "@Monto", DbType.Decimal, promocion.Monto);
            Db.AddInParameter(command, "@CantidadAcciones", DbType.Int32, promocion.CantidadAcciones);
            Db.AddInParameter(command, "@favorecerMultiplesVeces", DbType.Boolean, promocion.FavorecerMultiplesVeces);
            Db.ExecuteNonQuery(command);

            DeleteSorteos(promocion.Id);
            InsertSorteos(promocion.Sorteos, promocion.Id);
        }
        
        public static void Delete(int promocionId)
        {
            DeleteSorteos(promocionId);
            var command = Db.GetStoredProcCommand(DeleteSP);
            Db.AddInParameter(command, "@Id", DbType.Int32, promocionId);
            Db.ExecuteNonQuery(command);
        }

        public static void CargarConcursantesDesdeExcel(string archivo, int promocionId)
        {
            var connectionString = "Provider=Microsoft.Jet.OleDb.4.0;data source=" + archivo + ";Extended Properties=Excel 8.0;";
            var query = "Select Empresa, Nombre, Cedula, Telefono, MontoFactura from [Concursantes$]";
            var con = new OleDbConnection(connectionString);
            var adapter = new OleDbDataAdapter(query, con);
            var datasetExcel = new BEExcel();
            var fechaCarga = DateTime.Now;
            adapter.Fill(datasetExcel.CargaExcel);
            Db.ExecuteNonQuery(CommandType.Text, "DELETE cargaExcel WHERE promocionId=" + promocionId);
            
            var command = Db.GetStoredProcCommand(InsertCargaExcelSP);
            Db.AddInParameter(command, "@PromocionId", DbType.Int32, promocionId);
            Db.AddInParameter(command, "@Nombre", DbType.String);
            Db.AddInParameter(command, "@Cedula", DbType.String);
            Db.AddInParameter(command, "@Telefono", DbType.String);
            Db.AddInParameter(command, "@Empresa", DbType.String);
            Db.AddInParameter(command, "@MontoFactura", DbType.Decimal);
            Db.AddInParameter(command, "@FechaCarga", DbType.DateTime, fechaCarga);
            foreach (BEExcel.CargaExcelRow row in datasetExcel.CargaExcel.Rows)
            {
                command.Parameters["@Nombre"].Value = row.Nombre;
                command.Parameters["@Cedula"].Value = row.Cedula;
                command.Parameters["@Telefono"].Value = row.Telefono;
                command.Parameters["@Empresa"].Value = row.Empresa;
                command.Parameters["@MontoFactura"].Value = row.MontoFactura;
                Db.ExecuteNonQuery(command);
            }
        }

        public static void CalculaAcciones(int promocionId)
        {
            var command = Db.GetStoredProcCommand(CalculaAccionesSP);
            command.CommandTimeout = 300;   // 5 minutos
            Db.AddInParameter(command, "@promocionId", DbType.Int32, promocionId);
            Db.ExecuteNonQuery(command);
        }

        public static void Cleanup()
        {
            var command = Db.GetStoredProcCommand(CleanupSP);
            command.CommandTimeout = 300;   // 5 minutos
            Db.ExecuteNonQuery(command);
        }

        public static List<BEGanador> EjecutaSorteo(int sorteoId)
        {   
            var command = Db.GetStoredProcCommand(EjecutaSorteoSP);
            Db.AddInParameter(command, "@sorteoId", DbType.Int32, sorteoId);
            var result = new List<BEGanador>();
            var data = Db.ExecuteDataSet(command);
            if (data.Tables.Count == 1)
            {
                foreach (DataRow row in data.Tables[0].Rows)
                {
                    var ganador = CreateEntityFromDataRow<BEGanador>(row);
                    result.Add(ganador);
                }
            }
            return result;
        }

        public static List<BEGanador> EjecutaSorteo(DateTime inicio, DateTime final, int totalGanadores, bool favorecerMultiplesVeces)
        {
            var command = Db.GetStoredProcCommand(EjecutaSorteoPorFechasSP);
            Db.AddInParameter(command, "@fechaInicial", DbType.DateTime, inicio);
            Db.AddInParameter(command, "@fechaFinal", DbType.DateTime, final);
            Db.AddInParameter(command, "@totalGanadores", DbType.Int32, totalGanadores);
            Db.AddInParameter(command, "@favorecerMultiplesVeces", DbType.Boolean, favorecerMultiplesVeces);

            var result = new List<BEGanador>();
            var data = Db.ExecuteDataSet(command);
            if (data.Tables.Count == 1)
            {
                foreach (DataRow row in data.Tables[0].Rows)
                {
                    var ganador = CreateEntityFromDataRow<BEGanador>(row);
                    result.Add(ganador);
                }
            }
            return result;
        }

        #endregion

        #region Methods: Non-Public

        public static List<BEConcursanteReport> GetConcursantesReport(int promocionId, bool soloFavorecidos, string cedula, string nombre)
        {
            var result = new List<BEConcursanteReport>();
            var command = Db.GetStoredProcCommand(ReporteConcursantesSP);
            Db.AddInParameter(command, "@promocionId", DbType.Int32, promocionId);
            Db.AddInParameter(command, "@soloFavorecidos", DbType.Boolean, soloFavorecidos);
            Db.AddInParameter(command, "@filtroNombre", DbType.String, string.IsNullOrEmpty(nombre) ? Convert.DBNull : nombre);
            Db.AddInParameter(command, "@filtroCedula", DbType.String, string.IsNullOrEmpty(cedula) ? Convert.DBNull : cedula);
            
            var data = Db.ExecuteDataSet(command);
            if (data.Tables.Count == 1)
            {
                foreach (DataRow row in data.Tables[0].Rows)
                    result.Add(CreateEntityFromDataRow<BEConcursanteReport>(row));
            }
            return result;
        }

        private static void DeleteSorteos(int promocionId)
        {
            Db.ExecuteNonQuery(CommandType.Text, "DELETE sorteo WHERE promocionId = " + promocionId);
        }

        private static void InsertSorteos(IEnumerable<BESorteo> sorteos, int promocionId)
        {
            foreach (var item in sorteos)
            {
                var sorteoCommand = Db.GetStoredProcCommand(InsertSorteoSP);
                Db.AddInParameter(sorteoCommand, "@promocionId", DbType.Int32, promocionId);
                Db.AddInParameter(sorteoCommand, "@orden", DbType.Int32, item.Orden);
                Db.AddInParameter(sorteoCommand, "@ganadores", DbType.Int32, item.Ganadores);
                Db.AddInParameter(sorteoCommand, "@ejecutado", DbType.Boolean, item.Ejecutado);
                Db.ExecuteNonQuery(sorteoCommand);
            }
        }

        public static List<BESorteo> GetSorteoList()
        {
            var result = new List<BESorteo>();
            var command = Db.GetStoredProcCommand(GetSorteoListSP);
            var data = Db.ExecuteDataSet(command);
            if (data.Tables.Count == 1)
            {
                foreach (DataRow row in data.Tables[0].Rows)
                    result.Add(CreateEntityFromDataRow<BESorteo>(row));
            }
            return result;
        }

        #endregion
    }
}
